package net.qiqbframework.commandhandling.gateway;

import net.qiqbframework.commandhandling.CommandCallback;
import net.qiqbframework.commandhandling.CommandMessage;
import net.qiqbframework.commandhandling.GenericCommandMessage;
import net.qiqbframework.messaging.MetaData;
import net.qiqbframework.messaging.intercepting.MessageDispatchInterceptorSupport;

import javax.annotation.Nonnull;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;


public interface CommandGateway extends MessageDispatchInterceptorSupport<CommandMessage<?>> {
    /**
     * 发送命令。不等待结果
     *
     * @param command  命令载体
     * @param callback 命令回调
     * @param <C>      命令载体类型
     * @param <R>      结果载体类型
     */
    <C, R> void send(@Nonnull C command, @Nonnull CommandCallback<? super C, ? super R> callback);


    <R> CompletableFuture<R> send(@Nonnull Object command);


    <R> R sendAndWait(@Nonnull Object command);

    default <R> R sendAndWait(@Nonnull Object command, @Nonnull MetaData metaData) {
        final CommandMessage<Object> commandMessage = GenericCommandMessage.of(command);
        commandMessage.andMetaData(metaData);
        return sendAndWait(commandMessage);
    }


    <R> R sendAndWait(@Nonnull Object command, long timeout, @Nonnull TimeUnit unit);


    default <R> R sendAndWait(@Nonnull Object command, @Nonnull MetaData metaData, long timeout, @Nonnull TimeUnit unit) {
        final CommandMessage<Object> commandMessage = GenericCommandMessage.of(command);
        commandMessage.andMetaData(metaData);
        return sendAndWait(commandMessage, timeout, unit);
    }


    default <R> CompletableFuture<R> send(@Nonnull Object command, @Nonnull MetaData metaData) {
        final CommandMessage<Object> commandMessage = GenericCommandMessage.of(command);
        commandMessage.andMetaData(metaData);
        return send(commandMessage);
    }


    /**
     * 批量发送命令
     *
     * @param command
     * @param <R>
     * @return
     */
    <R> R batchSendAndWait(@Nonnull List<?> command);


}
